﻿using System;
using System.IO;
using CID.Execution.Support.Information;
using CID.Execution.Support.PackageHandling;
using ICSharpCode.SharpZipLib.Zip;

namespace CID.Execution.Agent.PackageHandling
{
    public class ZIPPackageHandler : FileSystemBasedPackageHandlerBase<ZIPPackageHandlingToken>
    {
        private const int BufferSize = 4096;

        protected override ZIPPackageHandlingToken CreatePackageHandlingToken(string tempPath, string packagePath)
        {
            return new ZIPPackageHandlingToken(tempPath, packagePath, Path.GetRandomFileName());
        }

        protected override void InternalPrepareForUsage(PackageInfo packageInfo, ZIPPackageHandlingToken packageHandlingToken)
        {
            var basePath = packageHandlingToken.TargetDirectoryPath;
            var buffer = new byte[BufferSize];

            Directory.CreateDirectory(basePath);

            using (var inputStream = File.Open(packageHandlingToken.SourceFilePath, FileMode.Open))
            {
                using (var zipStream = new ZipInputStream(inputStream))
                {
                    ZipEntry entry = null;
                    while ((entry = zipStream.GetNextEntry()) != null)
                    {
                        var fullPath = Path.Combine(basePath, entry.Name);
                        var directory = Path.GetDirectoryName(fullPath);
                        var fileName = Path.GetFileName(fullPath);

                        if (!Directory.Exists(directory))
                            Directory.CreateDirectory(directory);
                        
                        if (!String.IsNullOrEmpty(fileName))
                        {
                            using (var outputStream = File.Create(fullPath))
                            {
                                int count = 0;
                                while ((count = zipStream.Read(buffer, 0, BufferSize)) > 0)
                                    outputStream.Write(buffer, 0, count);
                                
                                outputStream.Flush();
                                outputStream.Close();
                            }
                        }
                    }
                    zipStream.Close();
                }
                inputStream.Close();
            }
        }

        protected override void InternalRelease(ZIPPackageHandlingToken packageHandlingToken)
        {
            Directory.Delete(packageHandlingToken.TargetDirectoryPath, true);
        }
    }
}
